package ufr_stgi.assistance_conduite.synchronisation;

import java.io.*;
import java.net.*;
import java.util.ArrayList;

import ufr_stgi.assistance_conduite.MonApplication;
import ufr_stgi.assistance_conduite.R;
import ufr_stgi.assistance_conduite.modele.Panneau;

import android.app.*;
import android.content.*;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.os.IBinder;
import android.os.Vibrator;
import android.util.Log;
import android.widget.*;

/**
 * Permet de lancer en tâche de fond l'upload vers le serveur de tous les panneaux enregistré par notre Smartphone
 * @author Guillaume MONTAVON & Renaud DAVID (Master 2 RIM)
 */
public class UploaderPanneaux extends Service{

	private MonApplication appli; //application
	private String urlEnvoi = MonApplication.adresseSeveur + "uploadNvPanneau"; //adresse de la requete à envoyer au serveur
	public final static int LARGEUR_IMAGE_UPLOADE = 1024; //largeur de l'image qui sera envoyé au serveur
	
	private int pourcentageTermine; //avancement actuel
	private int maxPourcentage; //avancement maximal
	private Notification notification;
	private NotificationManager notificationManager;
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		
		Log.i(this.getClass().getName(), "onCreate");
		pourcentageTermine = 0;
		maxPourcentage = 100;
		appli = (MonApplication)getApplication();
		
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.i(this.getClass().getName(), "fin de l'upload des panneaux");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(this.getClass().getName(), "onStartCommand");
		
		if(appli.reseauRapide())
			lancerUploadPanneaux();
		
		return START_NOT_STICKY; 
	}
	
	/**
	 * Permet d'envoyer au serveur distant la liste de tous les nouveaux panneaux enregistrés, qui n'ont pas encore été envoyés
	 */
	public void lancerUploadPanneaux() {
		
		appli.setEnCoursSynchro(true);
		
		boolean reussi = true;
		
		initNotification();
		
		ArrayList<Panneau> listePanneauxTemp = appli.getBdd().getListePanneauTemp();
		
		maxPourcentage = listePanneauxTemp.size();
		
		for(Panneau p : listePanneauxTemp) {
			
			if(envoiePanneau(p))
				appli.getBdd().supprimerPanneauTemp(p.getIdentifiant());
			else
				reussi = false;
			
			pourcentageTermine++;
			MAJPourcentage();
			
		}
		
		if(!reussi) {
			Log.e(getClass().getSimpleName(), "Une erreure s'est produite lors de l'envoi");
			Toast.makeText(this, "Une erreure s'est pproduite lors de l'envoi", Toast.LENGTH_SHORT).show();
			notification.contentView.setTextViewText(R.id.status_progress, appli.getString(R.string.synchro_upload_panneaux) + " " + appli.getString(R.string.notif_succes));
			Toast.makeText(appli, appli.getString(R.string.synchro_upload_panneaux) + " " + appli.getString(R.string.notif_succes), Toast.LENGTH_SHORT).show();
		}
		else {
			notification.contentView.setTextViewText(R.id.status_progress, appli.getString(R.string.synchro_upload_panneaux) + " " + appli.getString(R.string.notif_succes));
			Toast.makeText(appli, appli.getString(R.string.synchro_upload_panneaux) + " " + appli.getString(R.string.notif_succes), Toast.LENGTH_SHORT).show();
		}
		
		appli.getMain().MAJCaracteristiques();
		notificationManager.cancel(MonApplication.CODE_NOTIFICATION_UPLOAD);
		
		appli.setEnCoursSynchro(false);
	}
	
	
	/**
	 * Envoi le panneau donné en paramètre, avec son image associé, au serveur distant
	 * @param panneau panneau à envoyer au serveur
	 * @return true si l'opération s'est déroulée avec succès
	 */
	public synchronized boolean envoiePanneau(Panneau panneau) {
		
		String lineEnd = "\r\n";
		String twoHyphens = "--";
		String boundary = "*****";
		String httpResponse; // to read http response
		boolean reussi = true;
		
		HttpURLConnection conn = null;
		
		Bitmap mBitmap = null;
		
		try {
			mBitmap = BitmapFactory.decodeFile(new File(appli.getDossierImage(), panneau.getChemin()).getAbsolutePath());
			if(mBitmap != null && mBitmap.getWidth() != 0) {
				int hauteur = (int) Math.round(mBitmap.getHeight() * (LARGEUR_IMAGE_UPLOADE * 1.0 / mBitmap.getWidth()));
				mBitmap = Bitmap.createScaledBitmap(mBitmap, LARGEUR_IMAGE_UPLOADE, hauteur, true);
			}
		} catch (Exception e) {
			reussi = false;
		}
		
		if(mBitmap != null) {
			
			try {
				URL site = new URL(urlEnvoi);
				conn = (HttpURLConnection) site.openConnection();
				conn.setDoOutput(true); // on peut écrire
				conn.setDoInput(true); // et lire
				
				conn.setRequestMethod("POST"); // Use a post method.
				conn.setRequestProperty("Connection", "Keep-Alive");
				conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
				
				DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
				
				dos.writeBytes(twoHyphens + boundary + lineEnd);
				Log.i(getClass().getSimpleName(), "nom de l'image : " + panneau.getChemin());
				
				dos.writeBytes("Content-Disposition: form-data; name=\"latitude\"" + lineEnd + lineEnd + panneau.getLatitude() + lineEnd + twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"longitude\"" + lineEnd + lineEnd + panneau.getLongitude() + lineEnd + twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"direction\"" + lineEnd + lineEnd + panneau.getDirection() + lineEnd + twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"type\"" + lineEnd + lineEnd + panneau.getIdType() + lineEnd + twoHyphens + boundary + lineEnd);
				dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + panneau.getChemin() + "\"" + lineEnd);
				dos.writeBytes(lineEnd);
				
				
				mBitmap.compress(CompressFormat.JPEG, 75, dos); // compression de image pour envoi
				dos.writeBytes(lineEnd);
				dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); // send multipart form data necesssary after file data...
				
				dos.flush();
				dos.close(); // close streams
				Log.e("fileUpload", "File is written on the queue");
				
			} catch (MalformedURLException e) {
				reussi = false;
				Toast.makeText(this, "échec de connexion au site web ", Toast.LENGTH_SHORT) .show();
				Log.i(getClass().getSimpleName(), "échec de connexion au site web 1 : " + e.getMessage());
			} catch (IOException e) {
				reussi = false;
				Toast.makeText(this, "échec de connexion au site web ", Toast.LENGTH_SHORT).show();
				Log.i(getClass().getSimpleName(), "échec de connexion au site web 2" + e.getMessage());
			}
			
			// lecture de la réponse http
			try {
				BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
				Log.i(getClass().getSimpleName(), "try HTTP reponse");
				while ((httpResponse = rd.readLine()) != null) {
					Log.i(getClass().getSimpleName(), "HTTP reponse= " + httpResponse);
					if (httpResponse.contains("error") || httpResponse.contains("\"success\": false"))// there is a http error
						reussi = false;
				}
				rd.close();
			} catch (IOException ioex) {
				reussi = false;
				Log.e("UploaderPanneau", "error: " + ioex.getMessage(), ioex);
				Toast.makeText(this, "Echec de lecture de la réponse du site web ", Toast.LENGTH_SHORT).show();
			}
		
		}
		else {
			Log.e(getClass().getSimpleName(), "Impossible de lire l'image : " + panneau.getChemin());
			Toast.makeText(this, "Impossible de lire l'image : " + panneau.getChemin(), Toast.LENGTH_SHORT).show();
			reussi = false;
		}
		
		return reussi;
		
	}
	
	/**
	 * Vérifie si une image existe sur la carte SD
	 * @param nomFichier nom de l'image recherchée
	 * @return true si l'image est présente sur la carte SD
	 */
	public boolean existeImage(String nomFichier) {
		
		File fichier = new File(appli.getDossierImage(), nomFichier);
		return fichier.exists();
		
	}
	
	/**
	 * Met à jour l'avancement de l'opération dans la barre de notification
	 */
	public void MAJPourcentage() {
	
		notification.contentView.setProgressBar(R.id.status_progress, maxPourcentage, pourcentageTermine, false);
		notificationManager.notify(MonApplication.CODE_NOTIFICATION_UPLOAD, notification);
		if(pourcentageTermine >= maxPourcentage) {
			Vibrator v = (Vibrator) appli.getSystemService(MonApplication.VIBRATOR_SERVICE); // Get instance of Vibrator from current Context
			v.vibrate(300); // Vibrate for 300 milliseconds
		}
			
	
	}
	
	/**
	 * Initialisation de l'avancement de l'opération dans la barre de notification
	 */
	public void initNotification() {
		
		Intent intent = new Intent(appli, Synchronisation.class);
		final PendingIntent pendingIntent = PendingIntent.getActivity(appli.getApplicationContext(), 0, intent, 0);
		// configure the notification
		notification = new Notification(R.drawable.pan, appli.getString(R.string.synchro_upload_panneaux), System.currentTimeMillis());
		notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;
		//notification.defaults |= Notification.DEFAULT_SOUND;
		//notification.defaults |= Notification.DEFAULT_VIBRATE;
		notification.contentView = new RemoteViews(appli.getApplicationContext().getPackageName(), R.layout.upload_progress);
		notification.contentIntent = pendingIntent;
		notification.contentView.setImageViewResource(R.id.status_icon, R.drawable.pan);
		notification.contentView.setTextViewText(R.id.status_text, appli.getString(R.string.synchro_upload_panneaux) + appli.getString(R.string.notif_en_cours));
		notification.contentView.setProgressBar(R.id.status_progress, maxPourcentage, 0, false);
		
		notificationManager = (NotificationManager) appli.getApplicationContext().getSystemService(MonApplication.NOTIFICATION_SERVICE);
		notificationManager.notify(MonApplication.CODE_NOTIFICATION_UPLOAD, notification);
		
	}

}
